home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / PROG_TOO / C027B.ZIP / TOP / PEEP.C < prev    next >
Text File  |  1990-03-30  |  20KB  |  930 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. /*
  13.  * Peephole optimization routines
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18.  
  19. /*
  20.  * ipeep1(ip) - check for changes to the instruction 'ip'
  21.  */
  22. static    int
  23. ipeep1(bp, ip)
  24. register BLOCK    *bp;
  25. register INST    *ip;
  26. {
  27.     /*
  28.      * clr.l  Dn            => moveq.l  Dn
  29.      */
  30.     if (ip->opcode == CLR && ip->src.amode == REG &&
  31.         ISD(ip->src.areg) && (ip->flags & LENL)) {
  32.         ip->opcode = MOVEQ;
  33.         ip->dst = ip->src;    /* we'll have two operands now */
  34.         ip->src.amode = IMM;
  35.         ip->src.disp = 0;
  36.         return 1;
  37.     }
  38.  
  39.     /*
  40.      * move.*  #n,Dn        => moveq.*  #n,Dn
  41.      */
  42.     if (ip->opcode == MOVE && ip->src.amode == IMM && ISD(ip->dst.areg) &&
  43.         ip->flags == LENL && ip->src.disp >= -128  && ip->src.disp <= 127) {
  44.             ip->opcode = MOVEQ;
  45.             return 2;
  46.     }
  47.  
  48.     /*
  49.      * add.x  #n, Reg         => addq.x  #n, Reg
  50.      * where 1 <= n <= 8
  51.      */
  52.     if (ip->opcode == ADD && ip->src.amode == IMM && ip->dst.amode == REG &&
  53.         ip->src.disp >= 1 && ip->src.disp <= 8) {
  54.             ip->opcode = ADDQ;
  55.             return 3;
  56.     }
  57.  
  58.     /*
  59.      * sub.x  #n, Reg         => subq.x  #n, Reg
  60.      * where 1 <= n <= 8
  61.      */
  62.     if (ip->opcode == ADD && ip->src.amode == IMM && ip->dst.amode == REG &&
  63.         ip->src.disp >= 1 && ip->src.disp <= 8) {
  64.             ip->opcode = SUBQ;
  65.             return 4;
  66.     }
  67.  
  68.     /*
  69.      * movem.x  Reg,-(sp)        => move.x Reg,-(sp)
  70.      */
  71.     if (ip->opcode == MOVEM && ip->src.amode == REG &&
  72.         ip->dst.areg == SP && ip->dst.amode == (REGI|DEC)) {
  73.             ip->opcode = MOVE;
  74.             return 5;
  75.     }
  76.  
  77.     /*
  78.      * movem.x  (sp)+,Reg        => move.x (sp)+,Reg
  79.      */
  80.     if (ip->opcode == MOVEM && ip->dst.amode == REG &&
  81.         ip->src.amode == (REGI|INC) && ip->src.areg == SP) {
  82.             ip->opcode = MOVE;
  83.             return 6;
  84.     }
  85.  
  86.     /*
  87.      *    add[q]    #?,sp
  88.      *
  89.      *    Remove instruction if sp is dead.
  90.      */
  91.     if ((ip->opcode == ADDQ || ip->opcode == ADD) && ip->src.amode == IMM &&
  92.          ip->dst.amode == REG && ip->dst.areg == SP) {
  93.  
  94.         if (do_dflow && ((ip->live & RM(SP)) == 0)) {
  95.                  delinst(bp, ip);
  96.                  s_idel++;
  97.                  return 7;
  98.         }
  99.     }
  100.  
  101.     return 0;
  102. }
  103.  
  104. /*
  105.  * peep1(bp) - peephole optimizations with a window size of 1
  106.  *
  107.  * Returns TRUE if any optimizations were made.
  108.  */
  109. static    bool
  110. peep1(bp)
  111. register BLOCK    *bp;
  112. {
  113.     register INST    *ip;
  114.     register bool    changed = FALSE;
  115.     register int    pnum;
  116.  
  117. #ifdef    DEBUG
  118.     if (debug)
  119.         fprintf(stderr, "peep1: ");
  120. #endif
  121.     for (; bp != NULL ;bp = bp->next) {
  122.         for (ip = bp->first; ip != NULL ;) {
  123.             if (pnum = ipeep1(bp, ip)) {
  124.                 changed = TRUE;
  125.                 s_peep1++;
  126. #ifdef    DEBUG
  127.                 if (debug)
  128.                     fprintf(stderr, "%d ", pnum);
  129. #endif
  130.                 /*
  131.                  * Start over in case the instruction we
  132.                  * just looked at got deleted.
  133.                  */
  134.                 ip = bp->first;
  135.             } else
  136.                 ip = ip->next;
  137.         }
  138.     }
  139. #ifdef    DEBUG
  140.     if (debug)
  141.         fprintf(stderr, "\n");
  142. #endif
  143.  
  144.     return changed;
  145. }
  146.  
  147. /*
  148.  * ipeep2(bp, ip) - look for 2-instruction optimizations at the given inst.
  149.  */
  150. static    int
  151. ipeep2(bp, ip)
  152. register BLOCK    *bp;
  153. register INST    *ip;
  154. {
  155.     INST    *ni = ip->next;    /* the next instruction */
  156.     INST    *tni;        /* "temporary" next inst, for skipping */
  157.  
  158.     /*
  159.      *    addq    #4,sp
  160.      *    ... stuff that doesn't use SP ...
  161.      *    move.l    ?,-(sp)        =>    move.l    ?,(sp)
  162.      */
  163.     if (ip->opcode == ADDQ && ip->src.amode == IMM && ip->src.disp == 4 &&
  164.         ip->dst.amode == REG && ip->dst.areg == SP) {
  165.  
  166.         tni = ni;
  167.         while (do_dflow && !uses(tni, SP)) {
  168.             if (tni->next == NULL)
  169.                 return 0;
  170.             tni = tni->next;
  171.         }
  172.  
  173.         if (tni->opcode == MOVE && tni->flags == LENL &&
  174.             tni->dst.amode == (REGI|DEC) && tni->dst.areg == SP) {
  175.                 tni->dst.amode = REGI;
  176.                 delinst(bp, ip);
  177.                 s_idel++;
  178.                 return 1;
  179.         }
  180.     }
  181.  
  182.     /*
  183.      *    addq    #2,sp
  184.      *    ... stuff that doesn't use SP ...
  185.      *    move.w    ?,-(sp)        =>    move.w    ?,(sp)
  186.      */
  187.     if (ip->opcode == ADDQ && ip->src.amode == IMM && ip->src.disp == 2 &&
  188.         ip->dst.amode == REG && ip->dst.areg == SP) {
  189.  
  190.         tni = ni;
  191.         while (do_dflow && !uses(tni, SP)) {
  192.             if (tni->next == NULL)
  193.                 return 0;
  194.             tni = tni->next;
  195.         }
  196.  
  197.         if (tni->opcode == MOVE && tni->flags == LENW &&
  198.             tni->dst.amode == (REGI|DEC) && tni->dst.areg == SP) {
  199.                 tni->dst.amode = REGI;
  200.                 delinst(bp, ip);
  201.                 s_idel++;
  202.                 return 2;
  203.         }
  204.     }
  205.  
  206.     /*
  207.      *    move.x    X, Y        =>    move.x    X, Y
  208.      *    tst.x    Y            ...deleted...
  209.      *    beq/bne                beq/bne
  210.      *
  211.      *    Where Y is not An, because "movea" doesn't set the
  212.      *    zero flag.
  213.      */
  214.     if (bp->last == ni && (bp->bcode == BEQ || bp->bcode == BNE) &&
  215.         ip->opcode == MOVE && ni->opcode == TST &&
  216.         ip->flags == ni->flags) {
  217.  
  218.         int    is_dec = FALSE;
  219.  
  220.         /*
  221.          * If pre-decrement is set on the dest. of the move,
  222.          * don't let that screw up the operand comparison.
  223.          */
  224.         if (ip->dst.amode & DEC) {
  225.             is_dec = TRUE;
  226.             ip->dst.amode &= ~DEC;
  227.         }
  228.  
  229.         if (opeq(&ip->dst, &ni->src)) {
  230.             if (ip->dst.amode != REG || ISD(ip->dst.areg)) {
  231.                 if (is_dec)
  232.                     ip->dst.amode |= DEC;
  233.                     delinst(bp, ni);
  234.                     s_idel++;
  235.                     return 3;
  236.             }
  237.         }
  238.         if (is_dec)
  239.             ip->dst.amode |= DEC;
  240.     }
  241.  
  242.     /*
  243.      *    add[q]    #?,sp
  244.      *    ... stuff that doesn't use SP ...
  245.      *    unlk    An        =>    unlk    An
  246.      */
  247.     if ((ip->opcode == ADDQ || ip->opcode == ADD) && ip->src.amode == IMM &&
  248.          ip->dst.amode == REG && ip->dst.areg == SP) {
  249.  
  250.         tni = ni;
  251.         while (do_dflow && !uses(tni, SP)) {
  252.             if (tni->next == NULL)
  253.                 return 0;
  254.             tni = tni->next;
  255.         }
  256.         if (tni->opcode == UNLK) {
  257.                  delinst(bp, ip);
  258.                  s_idel++;
  259.                  return 4;
  260.         }
  261.     }
  262.  
  263.     /*
  264.      *    move.x    Dm, Dn        =>    move.x    Dm, Dn
  265.      *    move.x    Dn, Dm
  266.      */
  267.     if ((ip->opcode == MOVE) && (ni->opcode == MOVE) &&
  268.         (ip->src.amode == REG) && (ip->dst.amode == REG) &&
  269.         (ni->src.amode == REG) && (ni->dst.amode == REG)) {
  270.  
  271.         if (ISD(ip->src.areg) && (ip->src.areg == ni->dst.areg) &&
  272.             ISD(ip->dst.areg) && (ip->dst.areg == ni->src.areg)) {
  273.                  delinst(bp, ni);
  274.                  s_idel++;
  275.                  return 5;
  276.         }
  277.     }
  278.  
  279.     /*
  280.      *    move.l    Am, Dn        =>    move.l    Am, Ao
  281.      *    ... stuff ...            ... stuff ...
  282.      *    move.l    Dn, Ao
  283.      *
  284.      *    where "stuff" doesn't set Dn.
  285.      */
  286.     if ((ip->opcode == MOVE) && (ip->flags == LENL) &&
  287.         (ip->src.amode == REG) && ISA(ip->src.areg) &&
  288.         (ip->dst.amode == REG) && ISD(ip->dst.areg)) {
  289.  
  290.         tni = ni;
  291.         while (do_dflow && !sets(tni, ip->dst.areg)) {
  292.  
  293.             if ((tni->opcode == MOVE) && (tni->flags == LENL) &&
  294.                 (tni->src.amode == REG) && ISD(tni->src.areg) &&
  295.                 (tni->dst.amode == REG) && ISA(tni->dst.areg) &&
  296.                 (ip->dst.areg == tni->src.areg)) {
  297.     
  298.                 /*
  299.                  * If the intermediate register isn't dead,
  300.                  * then we have to keep using it.
  301.                  */
  302.                 if ((tni->live & RM(tni->src.areg)) != 0)
  303.                     return 0;
  304.     
  305.                 ip->dst.areg = tni->dst.areg;
  306.     
  307.                      delinst(bp, tni);
  308.                      s_idel++;
  309.                      return 6;
  310.             }
  311.  
  312.             if (tni->next == NULL)
  313.                 return 0;
  314.  
  315.             tni = tni->next;
  316.         }
  317.     }
  318.  
  319.     /*
  320.      *    sub.l    #1, Am
  321.      *    ... stuff ...
  322.      *    ???.b    ..(Am)..    =>    ???.b    ..-(Am)..
  323.      *
  324.      *    Nothing in "stuff" can refer to Am.
  325.      */
  326.     if ((ip->opcode == SUB) && (ip->flags & LENL) &&
  327.         (ip->src.amode == IMM) && (ip->src.disp == 1) &&
  328.         (ip->dst.amode == REG) && ISA(ip->dst.areg)) {
  329.  
  330.         int    rm = ip->dst.areg;
  331.  
  332.         while (ni != NULL) {
  333.  
  334.             if (ni->src.amode == REGI && ni->src.areg == rm) {
  335.  
  336.                 if ((ni->flags & LENB) == 0)
  337.                     return 0;
  338.  
  339.                 ni->src.amode |= DEC;
  340.  
  341.                     delinst(bp, ip);
  342.                     s_idel++;
  343.                     return 7;
  344.             }
  345.             if (ni->dst.amode == REGI && ni->dst.areg == rm) {
  346.  
  347.                 if ((ni->flags & LENB) == 0)
  348.                     return 0;
  349.  
  350.                 ni->dst.amode |= DEC;
  351.  
  352.                     delinst(bp, ip);
  353.                     s_idel++;
  354.                     return 7;
  355.             }
  356.  
  357.             if (uses(ni, RM(rm)))
  358.                 return 0;
  359.  
  360.             if (ni->next == NULL)
  361.                 return 0;
  362.             else
  363.                 ni = ni->next;
  364.  
  365.         }
  366.     }
  367.  
  368.     /*
  369.      *    sub.l    #2, Am
  370.      *    ... stuff ...
  371.      *    ???.w    ..(Am)..    =>    ???.w    ..-(Am)..
  372.      *
  373.      *    Nothing in "stuff" can refer to Am.
  374.      */
  375.     if ((ip->opcode == SUB) && (ip->flags & LENL) &&
  376.         (ip->src.amode == IMM) && (ip->src.disp == 2) &&
  377.         (ip->dst.amode == REG) && ISA(ip->dst.areg)) {
  378.  
  379.         int    rm = ip->dst.areg;
  380.  
  381.         while (ni != NULL) {
  382.  
  383.             if (ni->src.amode == REGI && ni->src.areg == rm) {
  384.  
  385.                 if ((ni->flags & LENW) == 0)
  386.                     return 0;
  387.  
  388.                 ni->src.amode |= DEC;
  389.  
  390.                     delinst(bp, ip);
  391.                     s_idel++;
  392.                     return 8;
  393.             }
  394.             if (ni->dst.amode == REGI && ni->dst.areg == rm) {
  395.  
  396.                 if ((ni->flags & LENW) == 0)
  397.                     return 0;
  398.  
  399.                 ni->dst.amode |= DEC;
  400.  
  401.                     delinst(bp, ip);
  402.                     s_idel++;
  403.                     return 8;
  404.             }
  405.  
  406.             if (uses(ni, RM(rm)))
  407.                 return 0;
  408.  
  409.             if (ni->next == NULL)
  410.                 return 0;
  411.             else
  412.                 ni = ni->next;
  413.  
  414.         }
  415.     }
  416.     /*
  417.      *    sub.l    #4, Am
  418.      *    ... stuff ...
  419.      *    ???.l    ..(Am)..    =>    ???.l    ..-(Am)..
  420.      *
  421.      *    Nothing in "stuff" can refer to Am.
  422.      */
  423.     if ((ip->opcode == SUB) && (ip->flags & LENL) &&
  424.         (ip->src.amode == IMM) && (ip->src.disp == 4) &&
  425.         (ip->dst.amode == REG) && ISA(ip->dst.areg)) {
  426.  
  427.         int    rm = ip->dst.areg;
  428.  
  429.         while (ni != NULL) {
  430.  
  431.             if (ni->src.amode == REGI && ni->src.areg == rm) {
  432.  
  433.                 if ((ni->flags & LENL) == 0)
  434.                     return 0;
  435.  
  436.                 ni->src.amode |= DEC;
  437.  
  438.                     delinst(bp, ip);
  439.                     s_idel++;
  440.                     return 9;
  441.             }
  442.             if (ni->dst.amode == REGI && ni->dst.areg == rm) {
  443.  
  444.                 if ((ni->flags & LENL) == 0)
  445.                     return 0;
  446.  
  447.                 ni->dst.amode |= DEC;
  448.  
  449.                     delinst(bp, ip);
  450.                     s_idel++;
  451.                     return 9;
  452.             }
  453.  
  454.             if (uses(ni, RM(rm)))
  455.                 return 0;
  456.  
  457.             if (ni->next == NULL)
  458.                 return 0;
  459.             else
  460.                 ni = ni->next;
  461.  
  462.         }
  463.     }
  464.     return 0;
  465. }
  466.  
  467. /*
  468.  * peep2(bp) - scan blocks starting at 'bp'
  469.  */
  470. static bool
  471. peep2(bp)
  472. register BLOCK    *bp;
  473. {
  474.     register INST    *ip;
  475.     register bool    changed = FALSE;
  476.     register int    pnum;
  477.  
  478. #ifdef    DEBUG
  479.     if (debug)
  480.         fprintf(stderr, "peep2: ");
  481. #endif
  482.  
  483.     for (; bp != NULL ;bp = bp->next) {
  484.         for (ip = bp->first; ip != NULL && ip->next != NULL ;) {
  485.             if (pnum = ipeep2(bp, ip)) {
  486.                 changed = TRUE;
  487.                 s_peep2++;
  488. #ifdef    DEBUG
  489.                 if (debug)
  490.                     fprintf(stderr, "%d ", pnum);
  491. #endif
  492.                 /*
  493.                  * If we had a match, then either instruction
  494.                  * may have been deleted, so the safe thing to
  495.                  * do is to start the block over.
  496.                  */
  497.                 ip = bp->first;
  498.             } else
  499.                 ip = ip->next;
  500.         }
  501.     }
  502. #ifdef    DEBUG
  503.     if (debug)
  504.         fprintf(stderr, "\n");
  505. #endif
  506.     return changed;
  507. }
  508.  
  509. /*
  510.  * ipeep3(bp, ip) - look for 3-instruction optimizations at the given inst.
  511.  */
  512. static    int
  513. ipeep3(bp, i1)
  514. register BLOCK    *bp;
  515. register INST    *i1;
  516. {
  517.     INST    *i2 = i1->next;        /* the next instruction */
  518.     INST    *i3 = i1->next->next;    /* the third instruction */
  519.  
  520.     /*
  521.      *    move.l    Am, Dn        =>    lea    N(Am), Ao
  522.      *    add.l    #N, Dn
  523.      *    move.l    Dn, Ao
  524.      *
  525.      *    Also, Dn must be dead after the third instruction.
  526.      */
  527.     if ((i1->opcode == MOVE) && (i1->flags & LENL) &&
  528.         (i1->src.amode == REG) &&
  529.         ISA(i1->src.areg) &&
  530.         (i1->dst.amode == REG) &&
  531.         ISD(i1->dst.areg)) {
  532.  
  533.         if (((i2->opcode == ADD) || (i2->opcode == ADDQ)) &&
  534.             (i2->flags & LENL) &&
  535.             (i2->src.amode == IMM) &&
  536.             DOK(i2->src.disp) &&
  537.             (i2->dst.amode == REG) &&
  538.             (i2->dst.areg == i1->dst.areg)) {
  539.  
  540.             if ((i3->opcode == MOVE) && (i3->flags & LENL) &&
  541.                 (i3->src.amode == REG) &&
  542.                 (i3->src.areg == i1->dst.areg) &&
  543.                 (i3->dst.amode == REG) &&
  544.                 ISA(i3->dst.areg) &&
  545.                 ((i3->live & RM(i3->src.areg)) == 0)) {
  546.  
  547.                 /*
  548.                  * rewrite i1 and delete i2 and i3
  549.                  */
  550.                 i1->opcode = LEA;
  551.                 i1->flags = 0;
  552.                 i1->dst = i3->dst;
  553.  
  554.                 i1->src.amode = REGID;
  555.                 i1->src.disp = i2->src.disp;
  556.  
  557.                     delinst(bp, i2);
  558.                     delinst(bp, i3);
  559.                     s_idel += 2;
  560.                     return 1;
  561.             }
  562.         }
  563.     }
  564.  
  565.     /*
  566.      *    move.l    Am, Dn        =>    lea    0(Am, Do), Ap
  567.      *    add.x    Do, Dn
  568.      *    move.l    Dn, Ap
  569.      *
  570.      *    The second instruction can be either a word or long add.
  571.      *    Also, Dn must be dead after the third instruction.
  572.      */
  573.     if ((i1->opcode == MOVE) && (i1->flags & LENL) &&
  574.         (i1->src.amode == REG) &&
  575.         ISA(i1->src.areg) &&
  576.         (i1->dst.amode == REG) &&
  577.         ISD(i1->dst.areg)) {
  578.  
  579.         if (((i2->opcode == ADD) || (i2->opcode == ADDQ)) &&
  580.             (i2->flags & (LENL|LENW)) &&
  581.             (i2->src.amode == REG) &&
  582.             ISD(i2->src.areg) && (i1->dst.areg != i2->src.areg) &&
  583.             (i2->dst.amode == REG) &&
  584.             (i2->dst.areg == i1->dst.areg)) {
  585.  
  586.             if ((i3->opcode == MOVE) && (i3->flags & LENL) &&
  587.                 (i3->src.amode == REG) &&
  588.                 (i3->src.areg == i1->dst.areg) &&
  589.                 (i3->dst.amode == REG) &&
  590.                 ISA(i3->dst.areg) &&
  591.                 ((i3->live & RM(i3->src.areg)) == 0)) {
  592.  
  593.                 /*
  594.                  * rewrite i1 and delete i2 and i3
  595.                  */
  596.                 i1->opcode = LEA;
  597.                 i1->flags = 0;
  598.                 i1->dst = i3->dst;
  599.  
  600.                 i1->src.amode = REGIDX;
  601.                 if (i2->flags & LENL)
  602.                     i1->src.amode |= XLONG;
  603.                 i1->src.ireg = i2->src.areg;
  604.                 i1->src.disp = 0;
  605.  
  606.                     delinst(bp, i2);
  607.                     delinst(bp, i3);
  608.                     s_idel += 2;
  609.                     return 2;
  610.             }
  611.         }
  612.     }
  613.  
  614.     /*
  615.      *    move.l    X(Am), Dn    =>    move.l    X(Am), Ao
  616.      *    add.l    #N, Dn
  617.      *    move.l    Dn, Ao            lea    N(Ao), Ao
  618.      *
  619.      *    Also, Dn must be dead after the third instruction.
  620.      */
  621.     if ((i1->opcode == MOVE) && (i1->flags & LENL) &&
  622.         (i1->src.amode == REGI || i1->src.amode == REGID) &&
  623.         (i1->dst.amode == REG) &&
  624.         ISD(i1->dst.areg)) {
  625.  
  626.         if (((i2->opcode == ADD) || (i2->opcode == ADDQ)) &&
  627.             (i2->flags & LENL) &&
  628.             (i2->src.amode == IMM) &&
  629.             DOK(i2->src.disp) &&
  630.             (i2->dst.amode == REG) &&
  631.             (i2->dst.areg == i1->dst.areg)) {
  632.  
  633.             if ((i3->opcode == MOVE) && (i3->flags & LENL) &&
  634.                 (i3->src.amode == REG) &&
  635.                 (i3->src.areg == i1->dst.areg) &&
  636.                 (i3->dst.amode == REG) &&
  637.                 ISA(i3->dst.areg) &&
  638.                 ((i3->live & RM(i3->src.areg)) == 0)) {
  639.  
  640.                 /*
  641.                  * rewrite i1 and i3 and delete i2
  642.                  */
  643.                 i1->dst = i3->dst;
  644.  
  645.                 i3->opcode = LEA;
  646.                 i3->flags = 0;
  647.                 i3->src.amode = REGID;
  648.                 i3->src.areg = i3->dst.areg;
  649.                 i3->src.disp = i2->src.disp;
  650.  
  651.                     delinst(bp, i2);
  652.                     s_idel++;
  653.                     return 3;
  654.             }
  655.         }
  656.     }
  657.  
  658.     /*
  659.      *    move.l    Am, An
  660.      *    addq.l    #1, Am
  661.      *    ... stuff ...
  662.      *    ???.b    ..(An)..    =>    ???.b    ..(Am)+..
  663.      *
  664.      *    An must be dead after the last instruction. Nothing in
  665.      *    "stuff" can modify Am.
  666.      */
  667.     if ((i1->opcode == MOVE) && (i1->flags & LENL) &&
  668.         (i1->src.amode == REG) && ISA(i1->src.areg) &&
  669.         (i1->dst.amode == REG) && ISA(i1->dst.areg)) {
  670.  
  671.         int    rm = i1->src.areg;
  672.         int    rn = i1->dst.areg;
  673.  
  674.         if (((i2->opcode == ADD) || (i2->opcode == ADDQ)) &&
  675.             (i2->flags & LENL) &&
  676.             (i2->src.amode == IMM) && (i2->src.disp == 1) &&
  677.             (i2->dst.amode == REG) &&
  678.             (i2->dst.areg == rm)) {
  679.  
  680.             while (i3 != NULL) {
  681.                 if (sets(i3, RM(rm)))
  682.                     return 0;
  683.  
  684.                 if (i3->src.amode==REGI && i3->src.areg==rn) {
  685.                     if (i3->live & RM(rn))
  686.                         return 0;
  687.  
  688.                     if ((i3->flags & LENB) == 0)
  689.                         return 0;
  690.  
  691.                     i3->src.amode |= INC;
  692.                     i3->src.areg = rm;
  693.  
  694.                         delinst(bp, i1);
  695.                         delinst(bp, i2);
  696.                         s_idel += 2;
  697.                         return 4;
  698.                 }
  699.                 if (i3->dst.amode==REGI && i3->dst.areg==rn) {
  700.                     if (i3->live & RM(rn))
  701.                         return 0;
  702.  
  703.                     if ((i3->flags & LENB) == 0)
  704.                         return 0;
  705.  
  706.                     i3->dst.amode |= INC;
  707.                     i3->dst.areg = rm;
  708.  
  709.                         delinst(bp, i1);
  710.                         delinst(bp, i2);
  711.                         s_idel += 2;
  712.                         return 4;
  713.                 }
  714.  
  715.                 if (i3->next == NULL)
  716.                     return 0;
  717.                 else
  718.                     i3 = i3->next;
  719.  
  720.             }
  721.         }
  722.     }
  723.  
  724.     /*
  725.      *    move.l    Am, An
  726.      *    addq.l    #2, Am
  727.      *    ... stuff ...
  728.      *    ???.w    ..(An)..    =>    ???.w    ..(Am)+..
  729.      *
  730.      *    An must be dead after the last instruction. Nothing in
  731.      *    "stuff" can modify Am.
  732.      */
  733.     if ((i1->opcode == MOVE) && (i1->flags & LENL) &&
  734.         (i1->src.amode == REG) && ISA(i1->src.areg) &&
  735.         (i1->dst.amode == REG) && ISA(i1->dst.areg)) {
  736.  
  737.         int    rm = i1->src.areg;
  738.         int    rn = i1->dst.areg;
  739.  
  740.         if (((i2->opcode == ADD) || (i2->opcode == ADDQ)) &&
  741.             (i2->flags & LENL) &&
  742.             (i2->src.amode == IMM) && (i2->src.disp == 2) &&
  743.             (i2->dst.amode == REG) &&
  744.             (i2->dst.areg == rm)) {
  745.  
  746.             while (i3 != NULL) {
  747.                 if (sets(i3, RM(rm)))
  748.                     return 0;
  749.  
  750.                 if (i3->src.amode==REGI && i3->src.areg==rn) {
  751.                     if (i3->live & RM(rn))
  752.                         return 0;
  753.  
  754.                     if ((i3->flags & LENW) == 0)
  755.                         return 0;
  756.  
  757.                     i3->src.amode |= INC;
  758.                     i3->src.areg = rm;
  759.  
  760.                         delinst(bp, i1);
  761.                         delinst(bp, i2);
  762.                         s_idel += 2;
  763.                         return 5;
  764.                 }
  765.                 if (i3->dst.amode==REGI && i3->dst.areg==rn) {
  766.                     if (i3->live & RM(rn))
  767.                         return 0;
  768.  
  769.                     if ((i3->flags & LENW) == 0)
  770.                         return 0;
  771.  
  772.                     i3->dst.amode |= INC;
  773.                     i3->dst.areg = rm;
  774.  
  775.                         delinst(bp, i1);
  776.                         delinst(bp, i2);
  777.                         s_idel += 2;
  778.                         return 4;
  779.                 }
  780.  
  781.                 if (i3->next == NULL)
  782.                     return 0;
  783.                 else
  784.                     i3 = i3->next;
  785.  
  786.             }
  787.         }
  788.     }
  789.     /*
  790.      *    move.l    Am, An
  791.      *    addq.l    #4, Am
  792.      *    ... stuff ...
  793.      *    ???.l    ..(An)..    =>    ???.l    ..(Am)+..
  794.      *
  795.      *    An must be dead after the last instruction. Nothing in
  796.      *    "stuff" can modify Am.
  797.      */
  798.     if ((i1->opcode == MOVE) && (i1->flags & LENL) &&
  799.         (i1->src.amode == REG) && ISA(i1->src.areg) &&
  800.         (i1->dst.amode == REG) && ISA(i1->dst.areg)) {
  801.  
  802.         int    rm = i1->src.areg;
  803.         int    rn = i1->dst.areg;
  804.  
  805.         if (((i2->opcode == ADD) || (i2->opcode == ADDQ)) &&
  806.             (i2->flags & LENL) &&
  807.             (i2->src.amode == IMM) && (i2->src.disp == 4) &&
  808.             (i2->dst.amode == REG) &&
  809.             (i2->dst.areg == rm)) {
  810.  
  811.             while (i3 != NULL) {
  812.                 if (sets(i3, RM(rm)))
  813.                     return 0;
  814.  
  815.                 if (i3->src.amode==REGI && i3->src.areg==rn) {
  816.                     if (i3->live & RM(rn))
  817.                         return 0;
  818.  
  819.                     if ((i3->flags & LENL) == 0)
  820.                         return 0;
  821.  
  822.                     i3->src.amode |= INC;
  823.                     i3->src.areg = rm;
  824.  
  825.                         delinst(bp, i1);
  826.                         delinst(bp, i2);
  827.                         s_idel += 2;
  828.                         return 6;
  829.                 }
  830.                 if (i3->dst.amode==REGI && i3->dst.areg==rn) {
  831.                     if (i3->live & RM(rn))
  832.                         return 0;
  833.  
  834.                     if ((i3->flags & LENL) == 0)
  835.                         return 0;
  836.  
  837.                     i3->dst.amode |= INC;
  838.                     i3->dst.areg = rm;
  839.  
  840.                         delinst(bp, i1);
  841.                         delinst(bp, i2);
  842.                         s_idel += 2;
  843.                         return 4;
  844.                 }
  845.  
  846.                 if (i3->next == NULL)
  847.                     return 0;
  848.                 else
  849.                     i3 = i3->next;
  850.  
  851.             }
  852.         }
  853.     }
  854.  
  855.     return 0;
  856. }
  857.  
  858. /*
  859.  * peep3(bp) - scan blocks starting at 'bp'
  860.  */
  861. static bool
  862. peep3(bp)
  863. register BLOCK    *bp;
  864. {
  865.     register INST    *ip;
  866.     register bool    changed = FALSE;
  867.     register int    pnum;
  868.  
  869.     /*
  870.      * All of the 3-inst stuff requires data-flow analysis
  871.      */
  872.     if (!do_dflow)
  873.         return FALSE;
  874.  
  875. #ifdef    DEBUG
  876.     if (debug)
  877.         fprintf(stderr, "peep3: ");
  878. #endif
  879.  
  880.     for (; bp != NULL ;bp = bp->next) {
  881.         ip = bp->first;
  882.         while (ip!=NULL && ip->next != NULL && ip->next->next != NULL) {
  883.             if (pnum = ipeep3(bp, ip)) {
  884.                 changed = TRUE;
  885.                 s_peep3++;
  886. #ifdef    DEBUG
  887.                 if (debug)
  888.                     fprintf(stderr, "%d ", pnum);
  889. #endif
  890.                 /*
  891.                  * If we had a match, then any instruction
  892.                  * could have been deleted, so the safe thing
  893.                  * to do is to start the block over.
  894.                  */
  895.                 ip = bp->first;
  896.             } else
  897.                 ip = ip->next;
  898.         }
  899.     }
  900. #ifdef    DEBUG
  901.     if (debug)
  902.         fprintf(stderr, "\n");
  903. #endif
  904.     return changed;
  905. }
  906.  
  907. void
  908. peep(bp)
  909. register BLOCK    *bp;
  910. {
  911.     extern    BLOCK    *fhead;
  912.     bool    changed;
  913.  
  914.     peep1(bp);
  915.  
  916.     /*
  917.      * Loop until no more changes are made. After each change, do
  918.      * live/dead analysis or the data gets old. In each loop, make
  919.      * at most one change.
  920.      */
  921.     for (changed = TRUE; changed ;rhealth(fhead)) {
  922.         if (peep2(bp))
  923.             changed = TRUE;
  924.         else if (peep3(bp))
  925.             changed = TRUE;
  926.         else
  927.             changed = FALSE;
  928.     }
  929. }
  930.